home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_12_06 / allison / merge2.c < prev    next >
C/C++ Source or Header  |  1994-04-08  |  2KB  |  97 lines

  1. LISTING 7 - C implementation of Listing 6
  2.  
  3. /* merge2.c: Merge up to 15 files to standard output */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define MAXFILES 15
  10.  
  11. static FILE *mustopen(char *, char *);
  12.  
  13. struct finfo
  14. {
  15.     FILE *f;
  16.     char line[BUFSIZ];
  17. };
  18.  
  19.  
  20. main(int argc, char *argv[])
  21. {
  22.     int i, min_idx;
  23.     int nfiles = argc - 1;  /* Number of active files */
  24.     struct finfo *files;
  25.  
  26.     if (nfiles == 0 || nfiles > MAXFILES)
  27.         return EXIT_FAILURE;
  28.  
  29.     /* Open files - read first line */
  30.     files = calloc(nfiles,sizeof(struct finfo));
  31.     if (!files)
  32.         return EXIT_FAILURE;
  33.     for (i = 0; i < nfiles; ++i)
  34.     {
  35.         files[i].f = mustopen(argv[i+1],"r");
  36.         fgets(files[i].line,BUFSIZ,files[i].f);
  37.     }
  38.  
  39.     /* Do the merge */
  40.     while (nfiles)
  41.     {
  42.         /* INVARIANT: At least one buffer has a fresh line */
  43.  
  44.         /* Determine which lines comes next and print it */
  45.         for (min_idx = 0, i = 1; i < nfiles; ++i)
  46.             if (strcmp(files[i].line,files[min_idx].line) < 0)
  47.                 min_idx = i;
  48.         fputs(files[min_idx].line,stdout);
  49.  
  50.         /* Get a fresh line from the corresponding file */
  51.         if (!fgets(files[min_idx].line,BUFSIZ,files[min_idx].f))
  52.         {
  53.             /* This file is finished */
  54.             fclose(files[min_idx].f);
  55.             files[min_idx] = files[--nfiles];
  56.         }
  57.     }
  58.     /* INVARIANT: all files have been closed */
  59.  
  60.     free(files);
  61.     return EXIT_SUCCESS;
  62. }
  63.  
  64. static FILE *mustopen(char *fname, char *mode)
  65. {
  66.     FILE *f = fopen(fname,mode);
  67.  
  68.     /* Open file or die */
  69.     if (!f)
  70.     {
  71.         fprintf(stderr,"Can't open %s.\n",fname);
  72.         exit(EXIT_FAILURE);
  73.     }
  74.     return(f);
  75. }
  76.  
  77. /* Sample execution:
  78. c:>merge2 file1.dat file2.dat file3.dat
  79. and
  80. brown
  81. cow
  82. dog
  83. fox
  84. jumped
  85. jumped
  86. lazy
  87. moon
  88. over
  89. over
  90. quick
  91. the
  92. the
  93. the
  94. the
  95. */
  96.  
  97.